#ifndef PGLOADER_H
#define PGLOADER_H

#include "Sington.h"
#include "PluginInfo.h"
#include <QObject>
#include <QQmlComponent>
#include <QQmlApplicationEngine>

#include <QLibrary>
#include <QThread>
#include <QReadWriteLock>

class QThread;

struct DllItem
{
    int m_idx;                  // 插件在配置文件中的下标
    QString m_fileName;         // 动态库的文件名
    QString m_path;             // 插件在文件系统中的路径
    PluginInfo* m_info;         // 与动态库的交互信息
};

struct PGLoaderConfig;

class PGLoader : public QObject
{
    Q_OBJECT
private:
    using PGEngine = QQmlApplicationEngine;
public:
    static PGLoader* instance();
    ~PGLoader();

    /**
     * @brief   : 根据配置文件加载全部dll文件,加载完毕后会发送loadComplete信号
     * @param   : engine 用于加载页面的渲染引擎
     * @author  : HXW
     * @version : v1.0
     * @date    : 2022-06-05 19:04:29
     */
    void load(PGLoader::PGEngine &engine);

    /**
     * @brief   : 新添扩展的dll
     * @param   : url 传入扩展dll的url连接，FileDialog的默认产生值
     * @author  : HXW
     * @version : v1.0
     * @date    : 2022-06-03 12:45:00
     * @details : 当使用全局后台线程运行，当添加完成后会发送，addDllComplete信号；
     *            需要注意的是，加载的时候会把用户指定的dll文件拷贝一份到默认extension的目录下面，
     *            在拷贝完成时会发送copyComplete信号。
     */
    Q_INVOKABLE void addExtensionDll(const QUrl& url);

    Q_INVOKABLE DllItem* getItem(int index);

    Q_INVOKABLE QList<DllItem> getItems();

    /**
     * @brief   : 获取PGLoader加载的外部扩展组件的个数
     * @return  : int 组件个数
     * @author  : HXW
     * @version : v1.0
     * @date    : 2022-06-24 11:04:04
     */
    Q_INVOKABLE int itemSize() const;

    Q_DISABLE_COPY_MOVE(PGLoader)

signals:
    void loadComplete();
    void curIdxChanged(QQmlComponent* component);
    void copyComplete();
    void addDllComplete(const QUrl& url);

public slots:

private:
    friend Sington<PGLoader>;
    PGLoader(QObject *parent = nullptr);    // 不可正常实例化，只允许全局出现一个PGLoader实例
    bool runInLoop() const;

private:
    using LibList  = QVector<std::shared_ptr<QLibrary>>;

    QThread *m_thread;
    mutable QReadWriteLock m_lock;          // used by m_dllItems
    QVector<DllItem> m_items;               // 动态加载的组件
    LibList m_libs;                         // 动态链接库
    PGLoaderConfig *m_config;               // 配置文件相关
};

#endif // PGLOADER_H

